home *** CD-ROM | disk | FTP | other *** search
/ Multimedia Madness 2 #12 / Multimedia Madness - Volume 2 - Issue 12 (SAMS Publishing) (November 25, 1992).iso / nemo / stringpp / str.cpp < prev    next >
C/C++ Source or Header  |  1992-10-08  |  11KB  |  564 lines

  1. /* -------------------------------------------------------------------- */
  2. /* String++ Version 2.10           str.cpp        Last revised 10/08/92 */
  3. /*                                                                      */
  4. /* Enhanced string class for Turbo C++/Borland C++.                     */
  5. /* Copyright 1991, 1992 by Carl W. Moreland                             */
  6. /* -------------------------------------------------------------------- */
  7.  
  8. #include <ctype.h>
  9. #include <stdlib.h>
  10. #include "str.h"
  11.  
  12. /* ----- Constructors/Destructors ------------------------------------- */
  13.  
  14. string::string()
  15. {
  16.   _ptr = new char[1];            // NULL string
  17.   _ptr[0] = '\0';
  18. }
  19.  
  20. string::string(const char c, unsigned n)
  21. {
  22.   _ptr = new char[n+1];            // allocate memory for n chars
  23.  
  24.   for(int i=0; i<n; i++)
  25.     _ptr[i] = c;             // copy n chars
  26.   _ptr[i] = '\0';            // NULL terminate
  27. }
  28.  
  29. string::string(const char *s, unsigned pos, unsigned len)
  30. {
  31.   int s_len = strlen(s);
  32.  
  33.   if(pos > s_len)
  34.     pos = s_len;
  35.   if(len > s_len - pos)
  36.     len = s_len - pos;
  37.  
  38.   _ptr = new char[len+1];        // allocate new memory
  39.  
  40.   strncpy(_ptr, s+pos, len);        // copy the substring
  41.   _ptr[len] = '\0';            // need to NULL terminate
  42. }
  43.  
  44. string::string(const string& s, unsigned pos, unsigned len)
  45. {
  46.   int s_len = s.Len();
  47.  
  48.   if(pos > s_len)
  49.     pos = s_len;
  50.   if(len > s_len - pos)
  51.     len = s_len - pos;
  52.  
  53.   _ptr = new char[len+1];        // allocate new memory
  54.  
  55.   strncpy(_ptr, s(pos), len);        // copy the substring
  56.   _ptr[len] = '\0';            // need to NULL terminate
  57. }
  58.  
  59. string::string(long n)
  60. {
  61.   char tmp[15];
  62.   ltoa(n, tmp, 10);
  63.  
  64.   _ptr = new char[strlen(tmp) + 1];
  65.   strcpy(_ptr, tmp);
  66. }
  67.  
  68. string::~string(void)
  69. {
  70.   if(_ptr)
  71.     delete _ptr;
  72. }
  73.  
  74. /* -------------------------------------------------------------------- */
  75.  
  76. string& string::Right(unsigned len)
  77. {
  78.   Mid(this->Len()-len, len);
  79.   return *this;
  80. }
  81.  
  82. string& string::Left(unsigned len)
  83. {
  84.   Mid(0, len);
  85.   return *this;
  86. }
  87.  
  88. string& string::Mid(unsigned pos, unsigned len)
  89. {
  90.   int s_len = Len();
  91.  
  92.   if(pos > s_len)
  93.     pos = s_len;
  94.   if(len > s_len - pos)
  95.     len = s_len - pos;
  96.  
  97.   char *tmp = new char[len+1];        // allocate new memory
  98.  
  99.   strncpy(tmp, _ptr+pos, len);        // copy the substring
  100.   tmp[len] = '\0';            // need to NULL terminate
  101.  
  102.   delete _ptr;
  103.   _ptr = tmp;
  104.   return *this;
  105. }
  106.  
  107. string& string::Justify(int mode, unsigned len, int clip)
  108. {
  109.   Trim();                // delete outter whitespace
  110.  
  111.   int this_len = Len();
  112.  
  113.   if(this_len >= len && clip == 0)    // check for out-of-bounds
  114.     return *this;
  115.  
  116.   if(this_len > len && clip == 1)    // check for clipping
  117.   {
  118.     if(mode == LEFT)
  119.       Left(len);
  120.     else if(mode == CENTER)
  121.       Mid((this_len-len)/2, len);
  122.     else if(mode == RIGHT)
  123.       Right(len);
  124.  
  125.     return *this;            // return clipped string
  126.   }
  127.  
  128.   if(mode == LEFT)
  129.     *this = *this + string(' ', len-this_len);
  130.   else if(mode == CENTER)
  131.     *this = string(' ', (len-this_len)/2) + *this + string(' ', len - (len+this_len)/2);
  132.   else if(mode == RIGHT)
  133.     *this = string(' ', len-this_len) + *this;
  134.  
  135.   return *this;                // return normal string
  136. }
  137.  
  138. string& string::toUpper(void)
  139. {
  140.   for(int i=0; i<strlen(_ptr); i++)
  141.     _ptr[i] = ::toupper(_ptr[i]);
  142.   return *this;
  143. }
  144.  
  145. string& string::toLower(void)
  146. {
  147.   for(int i=0; i<strlen(_ptr); i++)
  148.     _ptr[i] = ::tolower(_ptr[i]);
  149.   return *this;
  150. }
  151.  
  152. int& string::Value(int& n)
  153. {
  154.   n = atoi(_ptr);
  155.   return n;
  156. }
  157.  
  158. long& string::Value(long& n)
  159. {
  160.   n = atol(_ptr);
  161.   return n;
  162. }
  163.  
  164. string& string::Insert(unsigned pos, const string& s)
  165. {
  166.   int this_len = this->Len();
  167.   int s_len = s.Len();
  168.  
  169.   if(pos > this_len)
  170.     pos = this_len;
  171.  
  172.   char *tmp = new char[this_len + s_len + 1];
  173.  
  174.   strncpy(tmp, _ptr, pos);
  175.   tmp[pos] = '\0';
  176.   strcat(tmp, s.ptr());
  177.   strcat(tmp, _ptr+pos);
  178.  
  179.   delete _ptr;
  180.   _ptr = tmp;
  181.   return *this;
  182. }
  183.  
  184. string& string::Delete(unsigned pos, unsigned len)
  185. {
  186.   int this_len = this->Len();
  187.  
  188.   if(pos >= this_len)
  189.     return *this;
  190.   if(len == 0)
  191.     return *this;
  192.   if(len > this_len - pos)
  193.     len = this_len - pos;
  194.  
  195.   char *tmp = new char[this_len-len+1];
  196.  
  197.   strncpy(tmp, _ptr, pos);
  198.   tmp[pos] = '\0';
  199.   strcat(tmp, _ptr+pos+len);
  200.  
  201.   delete _ptr;
  202.   _ptr = tmp;
  203.   return *this;
  204. }
  205.  
  206. char* string::Copy(char *s)
  207. {
  208.   if(s)
  209.     delete s;
  210.   s = new char[Len() + 1];
  211.   strcpy(s, _ptr);
  212.  
  213.   return s;
  214. }
  215.  
  216. string& string::Trim(int mode, char ch)
  217. {
  218.   int begin = 0;
  219.   int end = this->Len()-1;
  220.  
  221.   if(ch == WHITESPACE)            // if we're deleting whitespaces...
  222.   {
  223.     if(mode == LEFT || mode == CENTER)    // delete leading whitespace
  224.     {
  225.       while(isspace(_ptr[begin]) && begin <= end)
  226.         begin++;
  227.     }
  228.  
  229.     if(mode == RIGHT || mode == CENTER)    // delete trailing whitespace
  230.     {
  231.       while(isspace(_ptr[end]) && end >= begin)
  232.         end--;
  233.     }
  234.   }
  235.   else                    // else a character was specified
  236.   {
  237.     if(mode == LEFT || mode == CENTER)    // delete leading characters
  238.     {
  239.       while(_ptr[begin] == ch && begin <= end)
  240.         begin++;
  241.     }
  242.  
  243.     if(mode == RIGHT || mode == CENTER)    // delete trailing characters
  244.     {
  245.       while(_ptr[end] == ch && end >= begin)
  246.         end--;
  247.     }
  248.   }
  249.  
  250.   int s_len = end-begin+1;
  251.   char *tmp = new char[s_len + 1];
  252.   strncpy(tmp, _ptr+begin, s_len);
  253.   tmp[s_len] = '\0';
  254.  
  255.   delete _ptr;
  256.   _ptr = tmp;
  257.   return *this;
  258. }
  259.  
  260. /* ----- Operators ---------------------------------------------------- */
  261.  
  262. string string::operator()(unsigned pos, unsigned len) const
  263. {
  264.   string tmp(this->_ptr, pos, len);
  265.   return tmp;
  266. }
  267.  
  268. // =
  269. string& string::operator=(const char ch)
  270. {
  271.   if(_ptr)
  272.     delete _ptr;
  273.  
  274.   _ptr = new char[2];
  275.   _ptr[0] = ch;
  276.   _ptr[1] = '\0';
  277.  
  278.   return *this;
  279. }
  280.  
  281. string& string::operator=(const char *s)
  282. {
  283.   char *tmp = _ptr;            // don't delete _ptr yet
  284.   _ptr = new char[strlen(s)+1];
  285.   strcpy(_ptr, s);
  286.  
  287.   if(tmp)
  288.     delete tmp;
  289.   return *this;
  290. }
  291.  
  292. string& string::operator=(const string& s)
  293. {
  294.   char *tmp = _ptr;            // don't delete _ptr yet
  295.   _ptr = new char[s.Len()+1];
  296.   strcpy(_ptr, s.ptr());
  297.  
  298.   if(tmp)
  299.     delete tmp;
  300.   return *this;
  301. }
  302.  
  303. string& string::operator=(const int n)
  304. {
  305.   if(_ptr)
  306.     delete _ptr;
  307.  
  308.   char tmp[15];
  309.   itoa(n, tmp, 10);
  310.  
  311.   _ptr = new char[strlen(tmp) + 1];
  312.   strcpy(_ptr, tmp);
  313.  
  314.   return *this;
  315. }
  316.  
  317. // +
  318. string operator+(const string& s1, const char *s2)
  319. {
  320.   string tmp(s1);
  321.   tmp += s2;
  322.   return tmp;
  323. }
  324.  
  325. string operator+(const char *s1, const string& s2)
  326. {
  327.   string tmp(s1);
  328.   tmp += s2;
  329.   return tmp;
  330. }
  331.  
  332. string operator+(const string& s1, const string& s2)
  333. {
  334.   string tmp(s1);
  335.   tmp += s2;
  336.   return tmp;
  337. }
  338.  
  339. // +=
  340. string& string::operator+=(const char ch)
  341. {
  342.   char *tmp = _ptr;
  343.   int this_len = this->Len();
  344.  
  345.   _ptr = new char[this_len + 2];
  346.  
  347.   strcpy(_ptr, tmp);
  348.   _ptr[this_len]   = ch;
  349.   _ptr[this_len+1] = '\0';
  350.  
  351.   if(tmp)
  352.     delete tmp;
  353.   return *this;
  354. }
  355.  
  356. string& string::operator+=(const char *s)
  357. {
  358.   char *tmp = _ptr;
  359.  
  360.   _ptr = new char[strlen(tmp) + strlen(s) + 1];
  361.  
  362.   strcpy(_ptr, tmp);
  363.   strcat(_ptr, s);
  364.  
  365.   if(tmp)
  366.     delete tmp;
  367.   return *this;
  368. }
  369.  
  370. string& string::operator+=(const string& s)
  371. {
  372.   char *tmp = _ptr;
  373.   _ptr = new char[strlen(tmp) + s.Len() + 1];
  374.  
  375.   strcpy(_ptr, tmp);
  376.   strcat(_ptr, s.ptr());
  377.  
  378.   if(tmp)
  379.     delete tmp;
  380.   return *this;
  381. }
  382.  
  383. // *
  384. string operator*(const string& s1, int n)
  385. {
  386.   string tmp(s1);
  387.  
  388.   for(int i=1; i<n; i++)
  389.     tmp += s1;
  390.   return tmp;
  391. }
  392.  
  393. // *=
  394. string& string::operator*=(unsigned n)
  395. {
  396.   char *tmp = _ptr;
  397.  
  398.   _ptr = new char[n*strlen(tmp) + 1];
  399.  
  400.   strcpy(_ptr, tmp);
  401.   for(int i=1; i<n; i++)
  402.     strcat(_ptr, tmp);
  403.  
  404.   if(tmp)
  405.     delete tmp;
  406.   return *this;
  407. }
  408.  
  409. // []
  410. char& string::operator[](unsigned n) const
  411. {
  412.   if(n >= Len())
  413.     n = Len()-1;
  414.   return *(_ptr + n);
  415. }
  416.  
  417. /* -------------------------------------------------------------------- */
  418. /* AWK-style functions                                                  */
  419. /* -------------------------------------------------------------------- */
  420.  
  421. int index(const string& s, const string& t)
  422. {
  423.   int pos;
  424.   char *tmp;
  425.  
  426.   if((tmp = strstr(s.ptr(), t.ptr())) != NULL)
  427.     pos = (int)(tmp-(const)s.ptr());
  428.   else
  429.     pos = -1;
  430.  
  431.   return pos;
  432. }
  433.  
  434. string substr(const string& s, unsigned p, unsigned n)
  435. {
  436.   string tmp = mid(s, p, n);
  437.   return tmp;
  438. }
  439.  
  440. int split(const string& s, string **array, const string& fs)
  441. {
  442.   int i=0, j=1, start=0;
  443.   int fs_len = fs.Len();
  444.   int s_len = s.Len();
  445.   string *tmp;
  446.  
  447.   while(i < s_len)
  448.   {
  449.     if(strncmp(s(i), fs(), fs_len) == 0)
  450.       j++;
  451.     i++;
  452.   }
  453.   tmp = new string[j];
  454.   i = 0;
  455.   j = 0;
  456.  
  457.   while(i < s_len)
  458.   {
  459.     if(strncmp(s(i), fs(), fs_len) == 0)
  460.     {
  461.       tmp[j++] = string(mid(s, start, i-start));
  462.       i += fs_len;
  463.       start = i;
  464.     }
  465.     else
  466.       i++;
  467.   }
  468.   tmp[j++] = mid(s, start, i-start);
  469.  
  470.   *array = tmp;
  471.   return j;
  472. }
  473.  
  474. int gsub(const string& from, const string& to, string& str, unsigned count)
  475. {
  476.   int i=0, j=0;
  477.   int from_len, to_len;
  478.  
  479.   from_len = from.Len();
  480.   to_len = to.Len();
  481.  
  482.   while(i <= str.Len()-from_len)
  483.   {
  484.     if(strncmp(str(i), from(), from_len) == 0)
  485.     {
  486.       str = left(str, i) + to + right(str, str.Len()-i-from_len);
  487.       i += to_len;
  488.       if(++j == count)
  489.         break;
  490.     }
  491.     else
  492.       i++;
  493.   }
  494.   return j;
  495. }
  496.  
  497. /* -------------------------------------------------------------------- */
  498. /* C-style functions                            */
  499. /* -------------------------------------------------------------------- */
  500.  
  501. string toupper(const string& s)
  502. {
  503.   string tmp(s);
  504.   tmp.toupper();
  505.   return tmp;
  506. }
  507.  
  508. string tolower(const string& s)
  509. {
  510.   string tmp(s);
  511.   tmp.tolower();
  512.   return tmp;
  513. }
  514.  
  515. string left(const string& s, unsigned len)
  516. {
  517.   string tmp(s, 0, len);
  518.   return tmp;
  519. }
  520.  
  521. string right(const string& s, unsigned len)
  522. {
  523.   string tmp(s, s.Len()-len, len);
  524.   return tmp;
  525. }
  526.  
  527. string mid(const string& s, unsigned pos, unsigned len)
  528. {
  529.   string tmp(s, pos, len);
  530.   return tmp;
  531. }
  532.  
  533. string justify(const string& s, int mode, unsigned len, int clip)
  534. {
  535.   string tmp(s);
  536.   tmp.Justify(mode, len, clip);
  537.   return tmp;
  538. }
  539.  
  540. string trim(const string& s, int mode)
  541. {
  542.   string tmp(s);
  543.   tmp.Trim(mode);
  544.   return tmp;
  545. }
  546.  
  547. /* ----- Stream I/O --------------------------------------------------- */
  548.  
  549. ostream& operator<<(ostream& s, const string& str)
  550. {
  551.   return s << str();
  552. }
  553.  
  554. istream& operator>>(istream& s, string& str)
  555. {
  556.   char p[256];
  557.  
  558.   s >> p;
  559.   str = p;
  560.  
  561.   return s;
  562. }
  563.  
  564.